#ifndef __MPHALPORT_H__
#define __MPHALPORT_H__

#include "wm_hal.h"
#include "csi_config.h"

#include "shared/runtime/interrupt_char.h"
#include "machine.h"


// 定义延时函数
#define mp_hal_delay_us_fast  mp_hal_delay_us

// mphal GPIO抽象接口
#define mp_hal_get_pin_obj(o)  (o)
#define MP_HAL_PIN_FMT         "%s"
#define mp_hal_pin_obj_t const machine_pin_obj_t *

#define mp_hal_pin_name(p)    gpio_search(p->pin, true, 0)
#define mp_hal_pin_input(p)   mp_hal_pin_cfg(p, GPIO_MODE_INPUT, GPIO_NOPULL)
#define mp_hal_pin_output(p)  mp_hal_pin_cfg(p, GPIO_MODE_OUTPUT, GPIO_NOPULL)

#define mp_hal_pin_read(p)      (HAL_GPIO_ReadPin(MICROPY_HW_PORT(p->pin), MICROPY_HW_PIN(p->pin)))
#define mp_hal_pin_write(p, v)   do{HAL_GPIO_WritePin(MICROPY_HW_PORT(p->pin), MICROPY_HW_PIN(p->pin), (GPIO_PinState)v);}while(0)


// 通过HAL_GetTick()返回, 对于us级延时函数来说, 直接使用减少调用开销
extern __IO uint32_t uwTick;    /* HAL_GetTick(){return uwTick;} */ 


// 返回CPU、WLAN、APB等时钟信息
static inline uint32_t __get_cpu_clk(void)
{
	wm_sys_clk sysclk;
	SystemClock_Get(&sysclk);
	return sysclk.cpuclk;
}

static inline uint32_t __get_wlan_clk(void)
{
	wm_sys_clk sysclk;
	SystemClock_Get(&sysclk);
	return sysclk.wlanclk;
}


static inline uint32_t __get_apb_clk(void)
{
    wm_sys_clk sysclk;
	SystemClock_Get(&sysclk);
	return sysclk.apbclk;
}

static inline mp_uint_t mp_hal_ticks_ms(void) {
    return  uwTick;  //HAL_GetTick();
}

static inline void mp_hal_delay_ms(mp_uint_t ms) {
	uint32_t tickstart = HAL_GetTick();
	uint32_t wait = ms;

	while ((HAL_GetTick() - tickstart) < wait){
		MICROPY_EVENT_POLL_HOOK
	}
}

static inline mp_uint_t mp_hal_ticks_us(void) {
	int utick = W805_PLL_CLK_MHZ / (uint8_t)(READ_REG(RCC->CLK_DIV)); // utick=480/psc=480/2=240(MHz), 1us计数240次
    return uwTick * 1000 + (CORET->LOAD - CORET->VAL) / utick;        // 直接返回毫秒数, 1us=1utick
}

//
// 参照stm32的做法, 读取systick(CORET)的计数值来做, CORET的计数频率等于CPU频率作(默认240MHz)
// 默认定时1KHz, period=240MHz/1KHz-1=240K-1, 因此1us计数240次
//
static inline void mp_hal_delay_us(mp_uint_t us) {
	
	uint32_t tus = CORET->VAL;            // 获取当前CORET计数器值, 若频率=240Mhz, 则1us=240 ticks
	uint32_t tms = uwTick;                // 毫秒级tick, 1ms=1 tick(CORET定时器每隔1ms对该值自增)
    mp_uint_t period = CORET->LOAD + 1;   // 1ms的计数周期
	int utick = W805_PLL_CLK_MHZ / (READ_REG(RCC->CLK_DIV)&0xFF); // utick=480/psc=480/2=240(MHz), 1us=240uticks
	
	// 毫秒*毫秒节拍数 + 开始节拍数/微秒节拍数 - 当前节拍数/微秒节拍数, CORET是向下计数器, 减到0, reload后继续
	while((uwTick-tms) * period + tus / utick - CORET->VAL / utick < us * utick);
}

static inline mp_uint_t mp_hal_ticks_cpu(void) {
    return 0;
}

//static inline void mp_hal_set_interrupt_char(int c) {
//}

extern uint64_t mp_hal_time_ns(void);
extern void mp_hal_pin_cfg(mp_hal_pin_obj_t pin, uint32_t mode, uint32_t pull);
#endif